using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Microblaze.Elf
{
  public abstract class ElfFormatEntity
  {
    private ElfFile elfFile;
    public ElfFile ElfFile
    {
      get { return elfFile; }      
    }

    public ElfFormatEntity(ElfFile elfFile)
    {
      this.elfFile = elfFile;
    }

    #region File Read Methods
    protected byte[] ReadBytes(BinaryReader reader, int count)
    {            
      return reader.ReadBytes(count);            
    }

    protected string ReadString(BinaryReader reader, int count)
    {
      // create the string using a build (for performance)
      StringBuilder str = new StringBuilder();

      // read the raw bytes
      byte[] bytes = reader.ReadBytes(count);
      
      // convert to string and return
      for(int i = 0; i < count; i++)
        str.Append((char) bytes[i]);

      return str.ToString();
    }

    protected ushort ReadElf32Half(BinaryReader reader)
    {
      byte b1 = reader.ReadByte();
      byte b2 = reader.ReadByte();

      ushort result = 0;

      if (elfFile.Identification.Ei_data == ElfIdentification.Ei_Data.ElfData2Msb)
      {
        result = (ushort)((b1 << 8) | b2);
      }
      else
      {
        result = (ushort)((b2 << 8) | b1);
      }

      return result;
    }

    protected byte ReadByte(BinaryReader reader)
    {
      return reader.ReadByte();
    }

    protected uint ReadElf32Word(BinaryReader reader)
    {
      byte b1 = reader.ReadByte();
      byte b2 = reader.ReadByte();
      byte b3 = reader.ReadByte();
      byte b4 = reader.ReadByte();

      uint result = 0;

      if (elfFile.Identification.Ei_data == ElfIdentification.Ei_Data.ElfData2Msb)
      {
        result =
          (uint)(b1 << 24) |
          (uint)(b2 << 16) |
          (uint)(b3 << 8) |
          (uint)(b4);
      }
      else
      {
        result =
          (uint)(b4 << 24) |
          (uint)(b3 << 16) |
          (uint)(b2 << 8) |
          (uint)(b1);
      }

      return result;
    }

    protected uint ReadElf32Off(BinaryReader reader)
    {
      return ReadElf32Word(reader);
    }

    protected uint ReadElf32Addr(BinaryReader reader)
    {
      return ReadElf32Word(reader);
    }

    #endregion
  }
}
